package app.services;

import app.Const;
import app.constant.OrderConstant;
import app.kit.SmsKit;
import app.kit.TypeKit;
import app.models.analyze.ProductRecord;
import app.models.member.BankCard;
import app.models.member.Member;
import app.models.member.MemberProduct;
import app.models.order.Order;
import app.models.product.Product;
import app.models.transfer.TransferProduct;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import goja.StringPool;
import goja.kits.ArithKit;
import org.joda.time.DateTime;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

import static app.Const.FIELD_CREATE_TIME;
import static app.Const.FIELD_MEMBER;
import static app.Const.FIELD_PRODUCT;
import static app.Const.FIELD_STATUS;
import static app.Const.FIELD_YIELD;
import static goja.StringPool.PK_COLUMN;

/**
 * <p> </p>
 *
 * @author sogYF
 * @version 1.0
 * @since JDK 1.6
 */
public class OrderService {
    /**
     * 获取单例对象,如果要调用该单例的使用,只能通过该方法获取.
     */
    public static OrderService me = new OrderService();

    /**
     * 私有构造函数,确保对象只能通过单例方法来调用.
     */
    private OrderService() {
    }


    public Order createBuyOrder(Member member, Product product) {
        return createOrder(member, product, OrderConstant.BUY_TYPE);
    }


    public Order createRpnOrder(int memberId, int productId, String productName, String productCode, double amount) {
        Order order = buildOrder(memberId, productId, productName, productCode, StringPool.EMPTY, OrderConstant.RPN_TYPE);
        order.set("trade_amount", amount);
        order.set(FIELD_STATUS, OrderConstant.HANDING);
        return order;
    }

    /**
     * 产品转让挂单订单
     *
     * @param memberId    会员
     * @param productId   产品
     * @param productName 产品名称
     * @param productCode 产品编码
     * @param amount      转让价格
     * @param fees        手续费
     * @return 订单信息
     */
    public Order createTransferPushOrder(int memberId, int productId, String productName, String productCode, BigDecimal amount, BigDecimal fees) {
        final Order order = buildOrder(memberId, productId, productName, productCode, StringPool.EMPTY, OrderConstant.TPUSH_TYPR);
        order.set("trade_amount", amount);
        order.set("fee_amonut", fees);
        return order;
    }

    /**
     * 创建转让订单
     *
     * @param memberId    会员
     * @param transferProduct 转让产品
     * @return 订单信息
     */
    public Order createTfrOrder(int memberId, final TransferProduct transferProduct) {

        int tranferProductId = TypeKit.getInt(transferProduct, PK_COLUMN);

        final Order order = buildOrder(memberId,
                TypeKit.getInt(transferProduct, Const.FIELD_PRODUCT),
                transferProduct.getStr(Const.FIELD_NAME),
                transferProduct.getStr(Const.FIELD_CODE),
                StringPool.EMPTY,
                OrderConstant.TFR_TYPE);
        order.set("transfer_product", tranferProductId);
        order.set("trade_amount", transferProduct.getBigDecimal(Const.FIELD_PRICE));

        order.save();

        // 为了统一处理 起息日计算，这里设置到 转让产品中，方便Controller调用
        transferProduct.put(Const.FIELD_VALUEDATEOFFSET, TypeKit.getInt(transferProduct, Const.FIELD_VALUEDATEOFFSET));

        return order;
    }


    /**
     * 创建转让订单
     *
     * @param memberId    会员
     * @param transferProduct 转让产品
     * @return 订单信息
     */
    public Order createTfrPayOrder(int memberId, final TransferProduct transferProduct, BigDecimal fee, BigDecimal lodging_amount, String srcOrderNo) {

        int tranferProductId = TypeKit.getInt(transferProduct, PK_COLUMN);

        final Order order = buildOrder(memberId,
                TypeKit.getInt(transferProduct, Const.FIELD_PRODUCT),
                transferProduct.getStr(Const.FIELD_NAME),
                transferProduct.getStr(Const.FIELD_CODE),
                StringPool.EMPTY,
                OrderConstant.TFR_PAY_TYPE);
        order.set("transfer_product", tranferProductId);
        order.set("fee_amonut", fee);
        order.set("lodging_amount", lodging_amount == null?BigDecimal.ZERO : lodging_amount);
        order.set("remark", "手续费、挂单费来源订单号：" + srcOrderNo);
        order.set("referer", srcOrderNo);

        return order;
    }


    /**
     * 生成订单
     *
     * @param member  会员
     * @param product 产品
     * @param type    订单类型
     * @return 订单信息
     */
    public Order createOrder(Member member, Product product, String type) {

        final int memberId = member.getNumber(PK_COLUMN).intValue();

        final Order order = buildOrder(memberId, product, type);

        order.save();

        return order;

    }

    /**
     * 生成订单
     *
     * @param member  会员
     * @param product 产品
     * @param type    订单类型
     * @param amount  投资金额
     * @return 订单信息
     */
    public Order createOrder(Member member, Product product, String type, BigDecimal amount) {



        final int memberId = member.getNumber(PK_COLUMN).intValue();
        final Order order = buildOrder(memberId, product, type);
        order.set("trade_amount", amount);

        order.save();

        return order;

    }

    /**
     * 通过产品构建订单
     *
     * @param memberId 会员ID
     * @param product  产品信息
     * @param type     订单类型
     * @return 订单信息
     */
    public Order buildOrder(int memberId, Product product, String type) {
        int product_id = TypeKit.getInt(product, PK_COLUMN);
        return buildOrder(memberId, product_id, product.getStr(Const.FIELD_NAME), product.getStr(Const.FIELD_CODE),
                product.getStr("simple_code"), type);

    }

    /**
     * 构建订单
     *
     * @param memberId          会员ID
     * @param productId         产品ID
     * @param productName       产品名称
     * @param productCode       产品编号
     * @param productSimpleCode 产品批次号
     * @param type              订单类型
     * @return 订单信息
     */
    public Order buildOrder(int memberId, int productId, String productName, String productCode, String productSimpleCode, String type) {
        final DateTime now_dt = DateTime.now();
        final Order order = new Order();
        order.set("trade_no", Strings.isNullOrEmpty(productSimpleCode) ? SerialService.orderCode() : SerialService.orderCode(productSimpleCode));
        order.set(FIELD_PRODUCT, productId);
        order.set("product_name", productName);
        order.set("product_no", productCode);
        order.set(FIELD_MEMBER, memberId);
        order.set("buy_time_year", now_dt.getYear());
        order.set("buy_time_month", now_dt.getMonthOfYear());
        order.set("buy_time_day", now_dt.getDayOfMonth());
        Date util_date = now_dt.toDate();
        order.set("buy_time", util_date);
        order.set("order_type", type);
        order.set("record_time", util_date);
        order.set(FIELD_CREATE_TIME, util_date);
        order.set("referer", 0);
        order.set(FIELD_STATUS, OrderConstant.NEW);
        order.set("interface_record", 0);
        order.set("remark", StringPool.EMPTY);
        order.set("fee_amonut", 0);
        order.set("lodging_amount", 0);
        return order;
    }

    /**
     * 产品购买确认
     *
     * @param order    订单
     * @param bankCard 银行卡
     * @param amount   金额
     * @param member   会员
     * @return 会员产品信息
     */
    public Optional<MemberProduct> confirm(Order order, BankCard bankCard, Double amount, Member member) {

        Preconditions.checkNotNull(amount, "金额不能为空");
        final String bank_card = bankCard.getStr("bank_card");

        // TODO 需要与银行接口进行交互处理打款

        order.set(FIELD_STATUS, OrderConstant.TRADE_SUCCESS);
//        order.set("pay_type", OrderConstant.PAYTYPE_BANKCARD);
        final DateTime now_time = DateTime.now();
        final Date now = now_time.toDate();
        order.set("confirm_date", now);
        order.set("trade_amount", amount);
        order.set("bug_bank_card", bank_card);


        if (order.update()) {

            final int product_id = order.getInt(FIELD_PRODUCT);
            final int member_id = member.getInt(PK_COLUMN);

            Product product = Product.dao.findById(product_id);

            MemberProduct memberProduct = new MemberProduct();
            memberProduct.set(FIELD_MEMBER, member_id);
            memberProduct.set(FIELD_PRODUCT, product_id);
            memberProduct.set("buy_date", now);
            memberProduct.set("buy_time", now);
            memberProduct.set(Const.FIELD_AMOUNT, amount);
            memberProduct.set("term", product.getInt(Const.FIELD_TIME_LIMIT));
            memberProduct.set(Const.FIELD_COLLECTION_MODE, product.getStr(Const.FIELD_COLLECTION_MODE));

            memberProduct.set(FIELD_YIELD, product.getFloat(FIELD_YIELD));
            memberProduct.set("bank_card", bank_card);
            if (memberProduct.save()) {
                // 纪录投资纪录
                ProductRecord.dao.record(product, member, amount, now_time);
                // 同步更新平均收益率
                calculateAvgYield(member_id);
                // 如果是募集类产品，则进行进度计算
//                final int type = product.getInt(FIELD_TYPE);
//                if (type == TYPE_RAISE || type == TYPE_INVEST) {
//                    product.updateProgress(amount);
//                }

                // 短信通知
                SmsKit.trade(amount, 0, member.getStr("phone"));

                return Optional.of(memberProduct);
            } else {
                return Optional.absent();
            }
        }

        return Optional.absent();
    }

    /**
     * 更新某个会员的平均收益率
     *
     * @param member_id 会员ID
     * @return 是否操作成功
     */
    private boolean calculateAvgYield(int member_id) {
        List<MemberProduct> products = MemberProduct.dao.findByMember(member_id);
        float count_yield = 0.0f;
        for (MemberProduct product : products) {
            count_yield = count_yield + product.getFloat(FIELD_YIELD);
        }
        final double div = ArithKit.div(count_yield, products.size(), 2) * 100;
        Member member = new Member();
        member.set(PK_COLUMN, member_id);
        member.set("avg_yield", div);
        member.update();
        return false;
    }
}
